// TreeService.ts
import {reactive, readonly, ref} from 'vue';
import { TreeNode } from './TreeNode';

export class TreeService {
    private readonly tree: TreeNode[];
    constructor() {
        this.tree = reactive<TreeNode[]>([]);
    }

    public getTree(): TreeNode[] {
        return this.tree;
    }

    public clearTree(){
        this.tree.pop();
    }

    public addRawData(node: TreeNode): void {
        this.tree.push(node);
    }

    public setRootTree(nodes: TreeNode[]):void{
        this.tree.pop();
        this.tree.concat(nodes);
    }

    public addNode(parentId: string, node: TreeNode): void {
        const parent = this.findNode(parentId);
        if (parent) {
            if (!parent.children) {
                parent.children = [];
            }
            parent.children.push(node);
        }
    }

    public addNodeList(parentId: string, nodes: TreeNode[]): void {
        const parent = this.findNode(parentId);
        if (parent) {
            parent.children = [];
            parent.children = nodes;
        }
    }

    public removeNode(nodeId: string): void {
        const parent = this.findParentNode(nodeId);
        if (parent) {
            parent.children = parent.children?.filter(node => node.id !== nodeId);
        }
    }

    public updateNode(nodeId: string, newNode: TreeNode): void {
        const node = this.findNode(nodeId);
        if (node) {
            node.title = newNode.title;
            node.type = newNode.type;
            node.checked = newNode.checked;
            node.spread = newNode.spread;
            node.children = newNode.children;
        }
    }

    private findNode(nodeId: string): TreeNode | undefined {
        const queue: TreeNode[] = [...this.tree];
        while (queue.length) {
            const node = queue.shift();
            if (node && node.id === nodeId) {
                return node;
            }
            if (node?.children) {
                queue.push(...node.children);
            }
        }
        return undefined;
    }

    private findParentNode(nodeId: string): TreeNode | undefined {
        const queue: TreeNode[] = [...this.tree];
        while (queue.length) {
            const node = queue.shift();
            if (node?.children) {
                const parentNode = node.children.find(child => child.id === nodeId);
                if (parentNode) {
                    return node;
                }
                queue.push(...node.children);
            }
        }
        return undefined;
    }

    public fundTargetNode(nodeId: string): TreeNode | undefined {
        // @ts-ignore
        return this.findNode(nodeId);
    }

    public fundTargetTables(ids: string[], node_type: string='db_table'): TreeNode[] | undefined {
        const tables : TreeNode[] = [];
        ids.forEach((nodeId) => {
            // @ts-ignore
            const current = this.findNode(nodeId);
            if(node_type === 'db_table' && current?.type === node_type){
                const tb: any = reactive({
                    id: current?.id,
                    db_id: current?.db_id,
                    database: current?.database,
                    table: current?.title,
                    columns: []
                })
                tables.push(tb);
            }
            if(node_type === 'db_table' && current?.type === 'db_field'){
                const lastNode = tables.pop();
                // @ts-ignore
                lastNode.columns.push(current.title);
                // @ts-ignore
                tables.push(lastNode);
            }
            if(node_type === 'db_field' && current?.type === node_type){
                const tb: any = reactive({
                    id: current?.id,
                    db_id: current?.db_id,
                    database: current?.database,
                    table: current?.table,
                    field: current?.title
                })
                tables.push(tb);
            }
        })
        return tables;
    };

    // 条件筛选
    public filterTree(root: TreeNode, condition: (node: TreeNode) => boolean): TreeNode | null {
        if (condition(root)) {
            root.spread = true;
            return root;
        }
        if (root.children) {
           const filteredChildren: TreeNode[] = [];
           for (const child of root.children) {
               const filteredChild = this.filterTree(child, condition);
               if (filteredChild) {
                   filteredChild.spread = true;
                   filteredChildren.push(filteredChild);
               }
           }
           if (filteredChildren.length > 0) {
               return { ...root, children: filteredChildren };
           }
        }
        return null;
    }
}
